#include <v8.h>
#include <iostream>


#include <string.h>
#include <stdlib.h>
#include <iconv.h>


using namespace v8;
using namespace std;

Handle<v8::Value> log(const v8::Arguments& args);
Handle<v8::Value> v8WriteFile(const v8::Arguments& args);
Handle<String> readFile(const char* name);
Handle<v8::Value> v8ReadFile(const v8::Arguments& args);
Handle<v8::Value> v8System(const v8::Arguments& args);
Handle<v8::Value> v8Markdown(const v8::Arguments& args);
Handle<v8::Value> v8ImportJs(const v8::Arguments& args);
Handle<v8::Value> v8Iconv(const v8::Arguments& args);
const char* ToCString(const v8::String::Utf8Value& value);
Handle<Context> context;

Handle<v8::Value> log(const v8::Arguments& args){
	v8::String::Utf8Value str(args[0]);
	const char* cstr = ToCString(str);
	printf("%s\n", cstr);
	return v8::Undefined();
}

Handle<v8::Value> v8System(const v8::Arguments& args){
	v8::String::Utf8Value work(args[0]);
	int len = work.length();
	char cmd[len+10];
	cmd[0] = '\0';
	const char* commond = ToCString(work);
	string toFile = ">_result";
	strcat(cmd,commond);
	strcat(cmd,toFile.c_str());
	system(cmd);
	return readFile("_result");
}

Handle<v8::Value> v8Markdown(const v8::Arguments& args){
	v8::String::Utf8Value work(args[0]);
	const char* commond = ToCString(work);
	FILE *read_fp;
	read_fp = popen("perl Markdown.pl _markdown_in","r");

	if (read_fp == NULL) return v8::Handle<v8::String>();
	char buffer[1023+1];
	int chars_read;
	memset(buffer,'\0',sizeof(buffer));
	chars_read = fread(buffer,sizeof(char),1023,read_fp);
	printf("%d",chars_read);
	printf("%s",buffer);
	pclose(read_fp);
	return v8::Handle<v8::String>();
	/*
	fseek(read_fp, 0, SEEK_END);
	int size = ftell(read_fp);
	rewind(read_fp);
	printf("%d",size);

	char* chars = new char[size + 1];
	chars[size] = '\0';
	for (int i = 0; i < size;) {
	    int read = fread(&chars[i], 1, size - i, read_fp);
	    i += read;
	}
	pclose(read_fp);
	printf("%s",chars);
	v8::Handle<v8::String> result = v8::String::New(chars, size);
	delete[] chars;
	return result;*/
}

Handle<v8::Value> v8ImportJs(const v8::Arguments& args){
	Handle<String> script, script_name;
	Handle<Script> mscript;
	int i=1, len = args.Length();
	if(len <= 0 )
		return v8::Undefined();

	v8::String::Utf8Value str(args[0]);
	script = readFile(ToCString(str));
	for(;i<len;i++){
		v8::String::Utf8Value strs(args[i]);
		script = v8::String::Concat(script,readFile(ToCString(strs)));
	}
	mscript = Script::Compile(script);
	mscript->Run();
	return v8::Undefined();
}


const char* ToCString(const v8::String::Utf8Value& value) {
  return *value ? *value : "<string conversion failed>";
}

Handle<v8::Value> v8Iconv(const v8::Arguments& args){
	v8::String::Utf8Value work(args[0]);
	const char* commond = ToCString(work);
	system(commond);

	return v8::Undefined();

}

Handle<v8::Value> v8ReadFile(const v8::Arguments& args) {
	v8::String::Utf8Value str(args[0]);
	const char* cstr = ToCString(str);

	return readFile(cstr);
}

Handle<v8::Value> v8WriteFile(const v8::Arguments& args){
	v8::String::Utf8Value fileName(args[0]);
	v8::String::Utf8Value fileContent(args[1]);
	const char* cFileName = ToCString(fileName);
	const char* cFileContent = ToCString(fileContent);
	FILE* file = fopen(cFileName, "wt");
	if (file == NULL) return v8::Handle<v8::String>();
	fputs(cFileContent,file);
	return v8::Undefined();
}

Handle<String> readFile(const char* name) {
  FILE* file = fopen(name, "rb");
  if (file == NULL) return v8::Handle<v8::String>();

  fseek(file, 0, SEEK_END);
  int size = ftell(file);
  rewind(file);

  char* chars = new char[size + 1];
  chars[size] = '\0';
  for (int i = 0; i < size;) {
    int read = fread(&chars[i], 1, size - i, file);
    i += read;
  }
  fclose(file);


/*

    iconv_t cd = iconv_open("UTF-8","GBK");
    if(cd == (iconv_t)-1){
    	printf("%s\n","hoho");
    }

    char *outbuf = (char *)malloc(size*4+1);
    char *in = chars;
    bzero(outbuf, size*4+1);
    char *out = outbuf;
    uint outlen = size*4+1;

    iconv(cd, &in,(size_t *)&size, &out, &outlen);
    printf("%s\n",outbuf);
    v8::Handle<v8::String> result = v8::String::New(outbuf, outlen);


    */
  v8::Handle<v8::String> result = v8::String::New(chars, size);
  delete[] chars;
  return result;
}

int main(int argc, char *argv[]){
	HandleScope scope;
	Handle<String> script, script_name;
	Handle<Script> mscript;
	Handle<ObjectTemplate> global_h = v8::ObjectTemplate::New();
	global_h->Set(v8::String::New("v8ReadFile"),v8::FunctionTemplate::New(v8ReadFile));
	global_h->Set(v8::String::New("v8Log"),v8::FunctionTemplate::New(log));
	global_h->Set(v8::String::New("v8ImportJs"),v8::FunctionTemplate::New(v8ImportJs));
	global_h->Set(v8::String::New("v8WriteFile"),v8::FunctionTemplate::New(v8WriteFile));
	global_h->Set(v8::String::New("v8Iconv"),v8::FunctionTemplate::New(v8Iconv));
	global_h->Set(v8::String::New("v8System"),v8::FunctionTemplate::New(v8System));
	global_h->Set(v8::String::New("v8Markdown"),v8::FunctionTemplate::New(v8Markdown));
	Handle<Context> context = Context::New(NULL,global_h);

	script = readFile("main.js");
	script_name = v8::String::New("vespa");
	Context::Scope cscope(context);
	mscript = Script::Compile(script);
	mscript->Run();


	return 0;
}
